package UtilsApplication;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import ModelApplication.Sound;

public class HandleAudioUtil {

    public static Sound loadSound(String path) {
        return loadSound(new File(path));
    }

    public static Sound loadSound(File file) {
        try {
            WavFile wavFile = WavFile.openWavFile(file);

            double[] signal = new double[(int) wavFile.getFramesRemaining()];

            double[][] buffer = new double[1][100];

            int framesRead;
            int signal_counter = 0; 
            do {
                framesRead = wavFile.readFrames(buffer, 100);
                for (int s = 0; s < framesRead; s++) {
                    signal[signal_counter * 100 + s] = buffer[0][s];
                }
                signal_counter++;

            } while (framesRead != 0);

            wavFile.close();

            Sound sound = new Sound(signal, wavFile, file);
            return sound;
        } catch(Exception e) {
            return null;
        }
    }

    public static List<Sound> loadSounds( String directory ) {
        List<Sound> sounds = new ArrayList<Sound>();
        File folder = new File(directory);
        File[] listOfFiles = folder.listFiles();

        for (int i = 0; i < listOfFiles.length; i++) {
            if (listOfFiles[i].isFile()) {
                sounds.add( loadSound(directory + File.separator + listOfFiles[i].getName()));
                System.out.println("File " + listOfFiles[i].getName());
            }
        }
        return sounds;
    }

    public static void saveAudio( Sound sound, File file ) {
        try {
            WavFile newWavFile = WavFile.newWavFile(file, 
                    sound.getWavFile().getNumChannels(), 
                    sound.getAudio().length, 
                    sound.getWavFile().getValidBits(), 
                    sound.getWavFile().getSampleRate());

            double[][] buffer = new double[1][100];

            long frameCounter = 0;
            double [] audio = sound.getAudio();
            int signal_counter = 0; 

            while (frameCounter < newWavFile.getNumFrames()) {
                long remaining = newWavFile.getFramesRemaining();
                int toWrite = (remaining > 100) ? 100 : (int) remaining;

                for (int s=0 ; s<toWrite ; s++, frameCounter++) {
                    //for(int i = 0; i < sound.getWavFile().getNumChannels(); i++) {
                    buffer[0][s] = audio[signal_counter * 100 + s];
                    //}
                }

                newWavFile.writeFrames(buffer, toWrite);
                signal_counter++;
            }
            newWavFile.close();
        } catch (Exception e) {
            System.err.println(e);
        }
    }
    
    public static double [] createTone(double freq, int samplesCount, int samplerate) {

      double [] audio = new double[samplesCount];

      for(int i = 0; i < samplesCount; i++)
      {
          double t = (double)i / (double)samplerate * 2 * Math.PI;
          audio[i] = (Math.sin(t * freq));
      }

      return audio;

  }

    public static double [] createTone(double freq, double top, int samplesCount, int samplerate) {
        double [] audio = new double[samplesCount];

        for(int i = 0; i < samplesCount; i++)
        {
            double t = (double)i / (double)samplerate * 2 * Math.PI;
            audio[i] = HandleAudioUtil.amplituda(top, samplesCount, i )*(Math.sin(t * freq));
        }

        return audio;
    }
    
    public static double amplituda(double top, double samplesCount, double i) {
        return (samplesCount - i)/samplesCount * top;
    }
    
    public static double[] normalizeSingal(double[] values) {
        double max = 0; double min = 0;
        for (int i = 0; i < values.length; i++) {
            if (max < values[i]) max = values[i];
            if (min > values[i]) min = values[i];
        }
        double ratioMin = (double)min;
        double ratioMax = (double)max;
        double ratio = 0;
        if (ratioMin < ratioMax)
            ratio = ratioMin;
        else
            ratio = ratioMax;
        for (int i = 0; i < values.length; i++) {
            values[i] = (double) ((double)values[i] / ratio);
        }
        return values;
    }
}
